package com.netease.yunxin.kit.conversationkit.ui.page

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.google.gson.Gson
import com.jeremyliao.liveeventbus.LiveEventBus
import com.luoxiang.lib_common.bean.NumberBean
import com.luoxiang.lib_common.common.Constants.MmkvConst.KEY
import com.luoxiang.lib_common.common.Constants.MmkvConst.KEY_CHECKSUM
import com.luoxiang.lib_common.common.Constants.MmkvConst.KEY_CURRTIME
import com.luoxiang.lib_common.common.Constants.MmkvConst.KEY_NONCE
import com.luoxiang.lib_common.common.Constants.MmkvConst.TOKEN
import com.luoxiang.lib_common.utils.AESUtil
import com.luoxiang.lib_common.utils.MmkvUtil.decodeString
import com.luoxiang.lib_common.utils.MmkvUtil.encode
import com.luoxiang.lib_common.utils.NetUtils
import com.netease.nimlib.sdk.NIMClient
import com.netease.nimlib.sdk.friend.model.MuteListChangedNotify
import com.netease.nimlib.sdk.msg.MsgService
import com.netease.nimlib.sdk.team.model.Team
import com.netease.yunxin.kit.common.ui.action.ActionItem
import com.netease.yunxin.kit.common.ui.dialog.AlertItemClickListener
import com.netease.yunxin.kit.common.ui.dialog.ListAlertDialog
import com.netease.yunxin.kit.common.ui.fragments.BaseFragment
import com.netease.yunxin.kit.common.ui.viewholder.BaseBean
import com.netease.yunxin.kit.common.ui.viewholder.ViewHolderClickListener
import com.netease.yunxin.kit.common.ui.viewmodel.FetchResult
import com.netease.yunxin.kit.common.ui.viewmodel.FetchResult.FetchType
import com.netease.yunxin.kit.common.ui.viewmodel.LoadStatus
import com.netease.yunxin.kit.conversationkit.model.ConversationInfo
import com.netease.yunxin.kit.conversationkit.ui.ConversationKitClient
import com.netease.yunxin.kit.conversationkit.ui.R
import com.netease.yunxin.kit.conversationkit.ui.common.ConversationConstant
import com.netease.yunxin.kit.conversationkit.ui.databinding.FragmentConversationItemBinding
import com.netease.yunxin.kit.conversationkit.ui.model.ConversationBean
import com.netease.yunxin.kit.conversationkit.ui.model.ImOfficialBean
import com.netease.yunxin.kit.conversationkit.ui.page.interfaces.ILoadListener
import com.netease.yunxin.kit.conversationkit.ui.page.viewmodel.ConversationViewModel
import com.netease.yunxin.kit.conversationkit.ui.view.ConversationAdapter
import com.netease.yunxin.kit.corekit.im.model.FriendInfo
import com.netease.yunxin.kit.corekit.im.model.UserInfo
import com.netease.yunxin.kit.corekit.route.XKitRouter.withKey
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.concurrent.TimeUnit

/**
 * Author: Sakura

 * Date: 2023/4/21

 * Description:
 */
class ConversationItemFragment : BaseFragment(), ILoadListener {

    private var binding: FragmentConversationItemBinding? = null

    private var viewModel: ConversationViewModel? = null

    private lateinit var changeObserver: Observer<FetchResult<List<ConversationBean>>>
    private lateinit var stickObserver: Observer<FetchResult<ConversationBean>>
    private lateinit var userInfoObserver: Observer<FetchResult<List<UserInfo>>>
    private lateinit var friendInfoObserver: Observer<FetchResult<List<FriendInfo>>>
    private lateinit var teamInfoObserver: Observer<FetchResult<List<Team>>>
    private lateinit var muteObserver: Observer<FetchResult<MuteListChangedNotify>>
    private lateinit var addRemoveStickObserver: Observer<FetchResult<String>>
    private var disposable: Disposable? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentConversationItemBinding.inflate(inflater, container, false)
        return binding?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProvider(this).get(
            ConversationViewModel::class.java
        )
        viewModel?.setComparator(conversationComparator)
        viewModel?.queryLiveData?.observe(
            this.viewLifecycleOwner
        ) { result: FetchResult<List<ConversationBean?>?> ->
            if (result.loadStatus == LoadStatus.Success) {
                binding?.conversationView?.setData(result.data)
                imOfficial()
            } else if (result.loadStatus == LoadStatus.Finish) {
                binding?.conversationView?.addData(result.data)
            }
            doCallback()
        }

        initObserver()
        initView()
        loadUIConfig()
        registerObserver()
        LiveEventBus.get<Any>("iMLoginSuccess").observeSticky(
            viewLifecycleOwner
        ) { o: Any? -> viewModel!!.fetchConversation() }
    }

    private fun loadUIConfig() {
        if (ConversationKitClient.getConversationUIConfig() != null
            && ConversationKitClient.getConversationUIConfig().conversationComparator != null
        ) {
            viewModel?.setComparator(
                ConversationKitClient.getConversationUIConfig().conversationComparator
            )
            binding?.conversationView?.setComparator(
                ConversationKitClient.getConversationUIConfig().conversationComparator
            )
        }
        if (ConversationKitClient.getConversationUIConfig() != null
            && ConversationKitClient.getConversationUIConfig().conversationFactory != null
        ) {
            viewModel?.setConversationFactory(
                ConversationKitClient.getConversationUIConfig().conversationFactory
            )
            binding?.conversationView?.setViewHolderFactory(
                ConversationKitClient.getConversationUIConfig().conversationFactory
            )
        }
    }

    private fun initView() {
        binding?.conversationView?.setComparator(conversationComparator)
        binding?.conversationView?.setItemClickListener(
            object : ViewHolderClickListener {
                override fun onClick(data: BaseBean, position: Int): Boolean {
                    var result = false
                    if (ConversationKitClient.getConversationUIConfig() != null && ConversationKitClient.getConversationUIConfig().itemClickListener != null && data is ConversationBean) {
                        result = ConversationKitClient.getConversationUIConfig().itemClickListener
                            .onClick(
                                requireContext(),
                                data,
                                position
                            )
                    }
                    if (!result) {
                        Log.d("routwrTag", data.router)
                        withKey(data.router)
                            .withParam(data.paramKey, data.param)
                            .withContext(requireContext())
                            .navigate()
                    }
                    return true
                }

                override fun onAvatarClick(data: BaseBean, position: Int): Boolean {
                    var result = false
                    if (ConversationKitClient.getConversationUIConfig() != null && ConversationKitClient.getConversationUIConfig().itemClickListener != null && data is ConversationBean) {
                        result = ConversationKitClient.getConversationUIConfig().itemClickListener
                            .onAvatarClick(
                                requireContext(),
                                data,
                                position
                            )
                    }
                    if (!result) {
                        withKey(data.router)
                            .withParam(data.paramKey, data.param)
                            .withContext(requireContext())
                            .navigate()
                    }
                    return true
                }

                override fun onLongClick(data: BaseBean, position: Int): Boolean {
                    var result = false
                    if (ConversationKitClient.getConversationUIConfig() != null && ConversationKitClient.getConversationUIConfig().itemClickListener != null && data is ConversationBean) {
                        result = ConversationKitClient.getConversationUIConfig().itemClickListener
                            .onLongClick(
                                requireContext(),
                                data,
                                position
                            )
                    }
                    if (!result) {
                        showStickDialog(data)
                    }
                    return true
                }

                override fun onAvatarLongClick(data: BaseBean, position: Int): Boolean {
                    var result = false
                    if (ConversationKitClient.getConversationUIConfig() != null && ConversationKitClient.getConversationUIConfig().itemClickListener != null && data is ConversationBean) {
                        result = ConversationKitClient.getConversationUIConfig().itemClickListener
                            .onAvatarLongClick(
                                requireContext(),
                                data,
                                position
                            )
                    }
                    if (!result) {
                        showStickDialog(data)
                    }
                    return true
                }
            })
    }

    private fun initObserver() {
        LiveEventBus.get<Boolean>("fetchConversation").observe(viewLifecycleOwner) {
            if (!it) return@observe
            viewModel?.fetchConversation()
        }
        LiveEventBus.get<Boolean>("OneClickRead").observe(viewLifecycleOwner) {
            if (!it) return@observe
            for (conversationBean in binding!!.conversationView.adapter.data) {
                // 跳过置顶用户
                if (viewModel?.StickTopList?.contains(conversationBean.infoData.contactId) == true) {
                    continue
                }
                // 跳过官方客服
                if (conversationBean.infoData.contactId == "100000" || conversationBean.infoData.contactId == "10000001") {
                    continue
                }
                // 删除本地历史记录
                NIMClient.getService(MsgService::class.java).deleteRecentContact(conversationBean.infoData)
                NIMClient.getService(MsgService::class.java).clearChattingHistory(
                    conversationBean.infoData.fromAccount,
                    conversationBean.infoData.sessionType,
                    false
                )
                if (conversationBean.infoData.contactId == "10000001") {
                    encode("officialNews", ConversationAdapter.imOfficialBean.data.officialMsgInfo.newestMsg.message.id)
                }
            }
        }
        changeObserver =
            androidx.lifecycle.Observer { result: FetchResult<List<ConversationBean>> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.update(result.data)
                } else if (result.loadStatus == LoadStatus.Finish
                    && result.type == FetchType.Remove
                ) {
                    if (result.data == null || result.data!!.isEmpty()) {
                        binding?.conversationView?.removeAll()
                    } else {
                        binding?.conversationView?.remove(result.data)
                    }
                }
                doCallback()
            }
        stickObserver =
            androidx.lifecycle.Observer { result: FetchResult<ConversationBean> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.update(result.data)
                }
                doCallback()
            }
        userInfoObserver =
            androidx.lifecycle.Observer { result: FetchResult<List<UserInfo>> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.updateUserInfo(result.data)
                }
            }
        friendInfoObserver =
            androidx.lifecycle.Observer { result: FetchResult<List<FriendInfo>> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.updateFriendInfo(result.data)
                }
            }
        teamInfoObserver =
            androidx.lifecycle.Observer { result: FetchResult<List<Team>> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.updateTeamInfo(result.data)
                }
            }
        muteObserver =
            androidx.lifecycle.Observer { result: FetchResult<MuteListChangedNotify> ->
                if (result.loadStatus == LoadStatus.Success) {
                    binding?.conversationView?.updateMuteInfo(result.data)
                }
            }
        addRemoveStickObserver =
            androidx.lifecycle.Observer { result: FetchResult<String> ->
                if (result.loadStatus == LoadStatus.Finish) {
                    if (result.type == FetchType.Add) {
                        binding?.conversationView?.addStickTop(result.data)
                    } else if (result.type == FetchType.Remove) {
                        binding?.conversationView?.removeStickTop(result.data)
                    }
                }
            }
    }

    private fun registerObserver() {
        viewModel?.changeLiveData?.observeForever(changeObserver)
        viewModel?.stickLiveData?.observeForever(stickObserver)
        viewModel?.userInfoLiveData?.observeForever(userInfoObserver)
        viewModel?.friendInfoLiveData?.observeForever(friendInfoObserver)
        viewModel?.teamInfoLiveData?.observeForever(teamInfoObserver)
        viewModel?.muteInfoLiveData?.observeForever(muteObserver)
        viewModel?.addRemoveStickLiveData?.observeForever(addRemoveStickObserver)
    }

    private fun unregisterObserver() {
        viewModel?.changeLiveData?.removeObserver(changeObserver)
        viewModel?.stickLiveData?.removeObserver(stickObserver)
        viewModel?.userInfoLiveData?.removeObserver(userInfoObserver)
        viewModel?.friendInfoLiveData?.removeObserver(friendInfoObserver)
        viewModel?.teamInfoLiveData?.removeObserver(teamInfoObserver)
        viewModel?.muteInfoLiveData?.removeObserver(muteObserver)
        viewModel?.addRemoveStickLiveData?.removeObserver(addRemoveStickObserver)
    }

    private fun showStickDialog(data: BaseBean) {
        if (data is ConversationBean) {
            if (data.infoData.contactId == "100000" || data.infoData.contactId == "10000001") {
                return
            }
            val dataBean = data
            val alertDialog = ListAlertDialog()
            alertDialog.setContent(generateDialogContent(dataBean.infoData.isStickTop))
            alertDialog.setTitleVisibility(View.GONE)
            alertDialog.dialogWidth = resources.getDimension(R.dimen.alert_dialog_width)
            alertDialog.itemClickListener = object : AlertItemClickListener {
                override fun onClick(action: String) {
                    if (TextUtils.equals(action, ConversationConstant.Action.ACTION_DELETE)) {
                        viewModel!!.deleteConversation(dataBean)
                        NIMClient.getService(
                            MsgService::class.java
                        ).clearChattingHistory(
                            dataBean.infoData.fromAccount,
                            dataBean.infoData.sessionType,
                            false
                        )
                        if (dataBean.infoData.contactId == "10000001") {
                            encode(
                                "officialNews",
                                ConversationAdapter.imOfficialBean.data.officialMsgInfo.newestMsg.message.id
                            )
                        }
                    } else if (TextUtils.equals(
                            action,
                            ConversationConstant.Action.ACTION_STICK
                        )
                    ) {
                        if (dataBean.infoData.isStickTop) {
                            viewModel!!.removeStick(data)
                        } else {
                            viewModel!!.addStickTop(
                                data,
                                binding?.conversationView?.adapter?.data?.get(0)
                            )
                        }
                    }
                    alertDialog.dismiss()
                }
            }
            alertDialog.show(parentFragmentManager)
        }
    }

    private fun imOfficial() {
        if (disposable != null) {
            return
        }
        disposable = Observable.interval(0, 10, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .subscribe { aLong: Long? ->
                getRequest()
                val token = decodeString(TOKEN)
                NetUtils.getInstance().apiService.imOfficial(token)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : io.reactivex.Observer<NumberBean?> {
                        override fun onSubscribe(d: Disposable) {}
                        override fun onNext(numberBean: NumberBean?) {
                            val data = numberBean?.data
                            var decryptStr: String? = null
                            try {
                                decryptStr =
                                    AESUtil.aesDecryptString(data, KEY)
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                            val imOfficialBean =
                                Gson().fromJson(
                                    decryptStr,
                                    ImOfficialBean::class.java
                                ) ?: return
                            val code = imOfficialBean.code
                            if (code != null && code == 0) {
                                binding?.conversationView?.addOfficial(imOfficialBean)
                            }
                        }

                        override fun onError(e: Throwable) {}
                        override fun onComplete() {}
                    })
            }
    }

    private fun generateDialogContent(isStick: Boolean): List<ActionItem> {
        val contentList: MutableList<ActionItem> = ArrayList()
        val stick = ActionItem(
            ConversationConstant.Action.ACTION_STICK,
            0,
            if (isStick) R.string.cancel_stick_title else R.string.stick_title
        )
        val delete = ActionItem(ConversationConstant.Action.ACTION_DELETE, 0, R.string.delete_title)
        contentList.add(stick)
        contentList.add(delete)
        return contentList
    }

    private fun doCallback() {

    }

    override fun onDestroyView() {
        super.onDestroyView()
        if (disposable != null) {
            disposable!!.dispose()
        }
        disposable = null
        unregisterObserver()
    }

    private val HEX_DIGITS = charArrayOf(
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    )

    private fun getRequest() {
        val apiKey = "17SgH6kkUNk8tyxjR6rbXEDiIR4P3nQh" //prod环境
        val nonce = (Math.random() * 9000 + 1000).toInt().toString() + "" //四位随机数
        val currTime = System.currentTimeMillis().toString() + "" //当前时间戳
        val value = apiKey + nonce + currTime
        var messageDigest: MessageDigest? = null
        try {
            messageDigest = MessageDigest.getInstance("sha1")
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
        messageDigest!!.update(value.toByteArray())
        val bytes = messageDigest.digest()

        //转换成16进制
        val len = bytes.size
        val buf = StringBuilder(len * 2)
        for (j in 0 until len) {
            buf.append(HEX_DIGITS[bytes[j].toInt() shr 4 and 0x0f])
            buf.append(HEX_DIGITS[bytes[j].toInt() and 0x0f])
        }
        val newCheckSum = buf.toString()
        encode(KEY_NONCE, nonce)
        encode(KEY_CURRTIME, currTime)
        encode(KEY_CHECKSUM, newCheckSum)
    }


    private val conversationComparator =
        java.util.Comparator { bean1: ConversationInfo?, bean2: ConversationInfo? ->
            var result = -1
            result = if (bean1 == null) {
                1
            } else if (bean2 == null) {
                -1
            } else if (bean1.isStickTop == bean2.isStickTop) {
                val time = bean1.time - bean2.time
                if (time == 0L) 0 else if (time > 0) -1 else 1
            } else {
                if (bean1.isStickTop) -1 else 1
            }
            result
        }

    override fun hasMore(): Boolean {
        return false
    }

    override fun loadMore(last: Any?) {

    }
}